<template>
	<view class="uv-subsection"
		ref="uv-subsection"
		:class="[`uv-subsection--${mode}`]"
		:style="[$uv.addStyle(customStyle), wrapperStyle]">
		<view class="uv-subsection__bar"
			ref="uv-subsection__bar"
			:style="[barStyle]"
			:class="[
                mode === 'button' && 'uv-subsection--button__bar',
                current === 0 &&
                    mode === 'subsection' &&
                    'uv-subsection__bar--first',
                current > 0 &&
                    current < list.length - 1 &&
                    mode === 'subsection' &&
                    'uv-subsection__bar--center',
                current === list.length - 1 &&
                    mode === 'subsection' &&
                    'uv-subsection__bar--last',
            ]"></view>
		<view class="uv-subsection__item"
			:class="[
                `uv-subsection__item--${index}`,
                index < list.length - 1 &&
                    'uv-subsection__item--no-border-right',
                index === 0 && 'uv-subsection__item--first',
                index === list.length - 1 && 'uv-subsection__item--last',
            ]"
			:ref="`uv-subsection__item--${index}`"
			:style="[itemStyle(index)]"
			@tap="clickHandler(index)"
			v-for="(item, index) in list"
			:key="index">
			<text class="uv-subsection__item__text"
				:style="[textStyle(index)]">{{ getText(item) }}</text>
		</view>
	</view>
</template>

<script>
	import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
	import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
	// #ifdef APP-NVUE
	const dom = uni.requireNativePlugin("dom");
	const animation = uni.requireNativePlugin("animation");
	// #endif
	import props from "./props.js";
	/**
	 * Subsection 分段器
	 * @description 该分段器一般用于用户从几个选项中选择某一个的场景
	 * @tutorial https://www.uvui.cn/components/subsection.html
	 * @property {Array}			list			tab的数据
	 * @property {String ｜ Number}	current			当前活动的tab的index（默认 0 ）
	 * @property {String}			activeColor		激活时的颜色（默认 '#3c9cff' ）
	 * @property {String}			inactiveColor	未激活时的颜色（默认 '#303133' ）
	 * @property {String}			mode			模式选择，mode=button为按钮形式，mode=subsection时为分段模式（默认 'button' ）
	 * @property {String ｜ Number}	fontSize		字体大小，单位px（默认 12 ）
	 * @property {Boolean}			bold			激活选项的字体是否加粗（默认 true ）
	 * @property {String}			bgColor			组件背景颜色，mode为button时有效（默认 '#eeeeef' ）
	 * @property {Object}			customStyle		定义需要用到的外部样式
	 * @property {String}	        keyName	        从`list`元素对象中读取的键名（默认 'name' ）
	 *
	 * @event {Function} change		分段器选项发生改变时触发  回调 index：选项的index索引值，从0开始
	 * @example <uv-subsection :list="list" :current="curNow" @change="sectionChange"></uv-subsection>
	 */
	export default {
		name: "uv-subsection",
		mixins: [mpMixin, mixin, props],
		data() {
			return {
				// 组件尺寸
				itemRect: {
					width: 0,
					height: 0,
				},
			};
		},
		watch: {
			list(newValue, oldValue) {
				this.init();
			},
			current: {
				immediate: true,
				handler(n) {
					// #ifdef APP-NVUE
					// 在安卓nvue上，如果通过translateX进行位移，到最后一个时，会导致右侧无法绘制圆角
					// 故用animation模块进行位移
					const ref = this.$refs?.["uv-subsection__bar"]?.ref;
					// 不存在ref的时候(理解为第一次初始化时，需要渲染dom，进行一定延时再获取ref)，这里的100ms是经过测试得出的结果(某些安卓需要延时久一点)，勿随意修改
					this.$uv.sleep(ref ? 0 : 100).then(() => {
						animation.transition(this.$refs["uv-subsection__bar"].ref, {
							styles: {
								transform: `translateX(${
                                n * this.itemRect.width
                            }px)`,
								transformOrigin: "center center",
							},
							duration: 300,
						});
					});
					// #endif
				},
			},
		},
		computed: {
			wrapperStyle() {
				const style = {};
				// button模式时，设置背景色
				if (this.mode === "button") {
					style.backgroundColor = this.bgColor;
				}
				return style;
			},
			// 滑块的样式
			barStyle() {
				const style = {};
				style.width = `${this.itemRect.width}px`;
				style.height = `${this.itemRect.height}px`;
				// 通过translateX移动滑块，其移动的距离为索引*item的宽度
				// #ifndef APP-NVUE
				style.transform = `translateX(${
                this.current * this.itemRect.width
            }px)`;
				// #endif
				if (this.mode === "subsection") {
					// 在subsection模式下，需要动态设置滑块的圆角，因为移动滑块使用的是translateX，无法通过父元素设置overflow: hidden隐藏滑块的直角
					style.backgroundColor = this.activeColor;
				}
				return style;
			},
			// 分段器item的样式
			itemStyle(index) {
				return (index) => {
					const style = {};
					if (this.mode === "subsection") {
						// 设置border的样式
						style.borderColor = this.activeColor;
						style.borderWidth = "1px";
						style.borderStyle = "solid";
					}
					return style;
				};
			},
			// 分段器文字颜色
			textStyle(index) {
				return (index) => {
					const style = {};
					style.fontWeight =
						this.bold && this.current === index ? "bold" : "normal";
					style.fontSize = this.$uv.addUnit(this.fontSize);
					// subsection模式下，激活时默认为白色的文字
					if (this.mode === "subsection") {
						style.color =
							this.current === index ? "#fff" : this.inactiveColor;
					} else {
						// button模式下，激活时文字颜色默认为activeColor
						style.color =
							this.current === index ?
							this.activeColor :
							this.inactiveColor;
					}
					return style;
				};
			},
		},
		mounted() {
			this.init();
		},
		methods: {
			init() {
				this.$uv.sleep().then(() => this.getRect());
			},
			// 判断展示文本
			getText(item) {
				return typeof item === 'object' ? item[this.keyName] : item
			},
			// 获取组件的尺寸
			getRect() {
				// #ifndef APP-NVUE
				this.$uvGetRect(".uv-subsection__item--0").then((size) => {
					this.itemRect = size;
				});
				// #endif

				// #ifdef APP-NVUE
				const ref = this.$refs["uv-subsection__item--0"][0];
				ref &&
					dom.getComponentRect(ref, (res) => {
						this.itemRect = res.size;
					});
				// #endif
			},
			clickHandler(index) {
				this.$emit("change", index);
			},
		},
	};
</script>

<style lang="scss" scoped>
	@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
	.uv-subsection {
		@include flex;
		position: relative;
		overflow: hidden;
		/* #ifndef APP-NVUE */
		width: 100%;
		box-sizing: border-box;
		/* #endif */
		&--button {
			height: 32px;
			background-color: rgb(238, 238, 239);
			padding: 3px;
			border-radius: 3px;
			align-items: stretch;
			&__bar {
				background-color: #ffffff;
				border-radius: 3px !important;
			}
		}
		&--subsection {
			height: 30px;
		}
		&__bar {
			position: absolute;
			/* #ifndef APP-NVUE */
			transition-property: transform, color;
			transition-duration: 0.3s;
			transition-timing-function: ease-in-out;
			/* #endif */
			&--first {
				border-top-left-radius: 3px;
				border-bottom-left-radius: 3px;
				border-top-right-radius: 0px;
				border-bottom-right-radius: 0px;
			}
			&--center {
				border-top-left-radius: 0px;
				border-bottom-left-radius: 0px;
				border-top-right-radius: 0px;
				border-bottom-right-radius: 0px;
			}
			&--last {
				border-top-left-radius: 0px;
				border-bottom-left-radius: 0px;
				border-top-right-radius: 3px;
				border-bottom-right-radius: 3px;
			}
		}
		&__item {
			@include flex;
			flex: 1;
			justify-content: center;
			align-items: center;
			// vue环境下，需要设置相对定位，因为滑块为绝对定位，item需要在滑块的上面
			position: relative;
			&--no-border-right {
				border-right-width: 0 !important;
			}
			&--first {
				border-top-left-radius: 3px;
				border-bottom-left-radius: 3px;
			}
			&--last {
				border-top-right-radius: 3px;
				border-bottom-right-radius: 3px;
			}
			&__text {
				font-size: 12px;
				line-height: 12px;
				@include flex;
				align-items: center;
				transition-property: color;
				transition-duration: 0.3s;
			}
		}
	}
</style>